package io.renren.modules.avanotes.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.*;
import io.renren.common.vo.output.SpecialSubjectOVo;
import io.renren.common.vo.output.SpecialSubjectVo;
import io.renren.config.BizConfig;
import io.renren.modules.avanotes.dao.SpecialSubjectDao;
import io.renren.modules.avanotes.entity.SpecialSubjectEntity;
import io.renren.modules.avanotes.entity.StudyScheduleEntity;
import io.renren.modules.avanotes.service.SpecialSubjectAchivmentEvaluationService;
import io.renren.modules.avanotes.service.SpecialSubjectService;
import io.renren.modules.avanotes.service.StudyScheduleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

//@Service("specialSubjectService")//默认只有一个实现，那就不写名称了直接使用默认的名称！
@Service
public class SpecialSubjectServiceImpl extends ServiceImpl<SpecialSubjectDao, SpecialSubjectEntity> implements SpecialSubjectService {

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    SpecialSubjectAchivmentEvaluationService achivmentEvaluationService;

    @Autowired
    StudyScheduleService studyScheduleService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpecialSubjectEntity> page = this.page(
                new Query<SpecialSubjectEntity>().getPage(params),
                new QueryWrapper<SpecialSubjectEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 根据ID 从缓存中获取数据
     *
     * @param id
     * @return
     */
    @Override
    public SpecialSubjectEntity getEntity(Integer id) throws Exception {
        String sid = "" + id;
        SpecialSubjectEntity entity = redisUtils.hGet(BizConfig.CACHE_SPECIAL_SUBJECT_ENTITY, sid, new TypeReference<SpecialSubjectEntity>() {
        });
        if (entity == null) {
            //为空，去DB
            entity = getById(id);
            if (entity == null) {
                return null;
            }
            //设置缓存
            redisUtils.hSet(BizConfig.CACHE_SPECIAL_SUBJECT_ENTITY, sid, JsonUtils.obj2String(entity));
        }
        return entity;
    }

    /**
     * 根据计划ID 分页查询对应专题数据
     *
     * @param page
     * @param scheduleId
     * @return
     */
    @Override
    public PageUtils queryPageByScheduleId(IPage<SpecialSubjectEntity> page, Long scheduleId) {
        IPage<SpecialSubjectEntity> pageByScheduleId = this.baseMapper.findPageByScheduleId(page, scheduleId);
        //获取计划
        StudyScheduleEntity studyEntity = studyScheduleService.getById(scheduleId);
        //获取用户
        Long userId = ShiroUtils.getUserEntity().getUserId();
        //对于是否评价过专题需要返回标志！
        //NOTEME 使用 Convert 完成转换
        int day = Integer.parseInt(DateUtils.format(new Date(), DateUtils.DATE_PATTERN_INT));
        IPage<SpecialSubjectOVo> convertPage = pageByScheduleId.convert(p -> {
            SpecialSubjectOVo vo = new SpecialSubjectOVo();
            BeanUtils.copyProperties(p, vo);
            //
             Integer count = achivmentEvaluationService.getCountByDateAndUserIdAndSpecialId(day, vo.getId(), userId);
            vo.setHasEva(count > 0);
            return vo;
        });

//        List<SpecialSubjectEntity> records = pageByScheduleId.getRecords();
//        List<SpecialSubjectOVo> list = new ArrayList<>();
//        for (SpecialSubjectEntity record : records) {
//            SpecialSubjectOVo vo = new SpecialSubjectOVo();
//            BeanUtils.copyProperties(record, vo);
//            //
//            Integer count = achivmentEvaluationService.getCountByDateAndUserIdAndSpecialId(studyEntity.getDay(), vo.getId(), userId);
//            vo.setHasEva(count > 0);
//
//            list.add(vo);
//        }
        //这里处理比较麻烦，所以用上面的方式
//        pageByScheduleId.setRecords(list);
        return new PageUtils(convertPage);
    }

    @Override
    public List<SpecialSubjectVo> listTree(Integer mindBookId) {
        List<SpecialSubjectEntity> list = this.list(new QueryWrapper<SpecialSubjectEntity>().eq(SpecialSubjectEntity.CN_MIND_BOOK_ID, mindBookId));

        //1.生成 Map
        Map<Integer, List<SpecialSubjectEntity>> map = genMap(list);
        //2.组装结果
        SpecialSubjectVo rootNode = genTreeByMap(map);
        List<SpecialSubjectVo> resList = new ArrayList<>();
        for (SpecialSubjectVo vo : rootNode.getChildren()) {
            resList.add(vo);
        }
        return resList;
    }

    private SpecialSubjectVo genTreeByMap(Map<Integer, List<SpecialSubjectEntity>> map) {
        List<SpecialSubjectVo> ll = new ArrayList<>();
        //即 root
        SpecialSubjectEntity firstEntity = map.get(0).get(0);
        SpecialSubjectVo firstNode = new SpecialSubjectVo();
        BeanUtils.copyProperties(firstEntity, firstNode);
        firstNode.init();

        ll.add(firstNode);
        genTreeByNode(firstNode, map, ll);
        return firstNode;
    }

    /**
     * pNode 保证在上一层已经处理：进 list
     *
     * @param pNode
     * @param map
     */
    private void genTreeByNode(SpecialSubjectVo pNode, Map<Integer, List<SpecialSubjectEntity>> map, List<SpecialSubjectVo> ll) {
        //子集合
        List<SpecialSubjectEntity> entityList = map.get(pNode.getId());
        if (CollectionUtils.isEmpty(entityList)) {
            pNode.setChildren(null);
            return;
        }
        //
        List<SpecialSubjectVo> childrenList = new ArrayList<>();
        for (SpecialSubjectEntity entity : entityList) {
            SpecialSubjectVo node = new SpecialSubjectVo();
            BeanUtils.copyProperties(entity, node);
            node.init();
            //如果超时5个字只截取5个
//            if (node.getName().length() > 5) {
//                node.setName(node.getName().substring(0, 5));
//            }

            genTreeByNode(node, map, ll);

            ll.add(node);
            childrenList.add(node);
        }
        pNode.setChildren(childrenList);
    }


    private Map<Integer, List<SpecialSubjectEntity>> genMap(List<SpecialSubjectEntity> list) {
        Map<Integer, List<SpecialSubjectEntity>> map = new HashMap<>();
        for (SpecialSubjectEntity entity : list) {
            if (map.containsKey(entity.getParentId())) {
                map.get(entity.getParentId()).add(entity);
            } else {
                ArrayList<SpecialSubjectEntity> ll = new ArrayList<>();
                ll.add(entity);
                map.put(entity.getParentId(), ll);
            }
        }
        return map;
    }

}